package com.mlethe.library.multi.api;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.credentials.ClearCredentialStateRequest;
import androidx.credentials.CredentialManager;
import androidx.credentials.CredentialManagerCallback;
import androidx.credentials.exceptions.ClearCredentialException;

import com.alipay.share.sdk.openapi.APAPIFactory;
import com.alipay.share.sdk.openapi.IAPApi;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.QueryPurchasesParams;
import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookSdk;
import com.facebook.login.LoginManager;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.mlethe.library.multi.api.entity.GooglePurchase;
import com.mlethe.library.multi.api.entity.InstalledState;
import com.mlethe.library.multi.api.entity.PlatformConfig;
import com.mlethe.library.multi.api.listener.Callback;
import com.mlethe.library.multi.api.listener.OnActionCallback;
import com.mlethe.library.multi.api.listener.OnActionListener;
import com.out.UPAuthStart;
import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.openapi.IWBAPI;
import com.sina.weibo.sdk.openapi.SdkListener;
import com.sina.weibo.sdk.openapi.WBAPIFactory;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import com.tencent.mm.opensdk.utils.Log;
import com.tencent.mobileqq.openpay.api.IOpenApi;
import com.tencent.mobileqq.openpay.api.OpenApiFactory;
import com.tencent.tauth.Tencent;
import com.unionpay.UPPayAssistEx;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HttpsURLConnection;

/**
 * 第三方登录、支付和分享工具管理类
 *
 * @author Mlethe
 * @date 2021/5/19
 */
public final class MultiApi {

    private final Map<MultiMedia, Platform> configs = new HashMap<>();

    /**
     * 安装状态缓存
     */
    private final Map<MultiMedia, InstalledState> installedStateCache = new HashMap<>();

    /**
     * 上下文
     */
    private Context mContext;

    /**
     * 主线程handler
     */
    private final Handler mHandler = new Handler(Looper.getMainLooper());

    /**
     * 微信、QQ、微博分享provider
     */
    private String mAuthorities;

    /**
     * 是否为调试模式
     */
    private boolean isDebug;

    /**
     * 微信对象
     */
    private IWXAPI mWXApi;

    /**
     * QQ 钱包支付对象
     */
    private IOpenApi mOpenApi;

    /**
     * QQ 授权登录和分享对象
     */
    private Tencent mTencent;

    /**
     * 支付宝分享对象
     */
    private IAPApi mAPApi;

    /**
     * 微博授权登录和分享对象
     */
    private IWBAPI mWBApi;

    /**
     * Facebook授权登录和分享对象
     */
    private CallbackManager mCallbackManager;

    /**
     * Google 认证管理对象
     */
    private CredentialManager mCredentialManager;

    /**
     * Google 支付对象（需要每次连接都是新的）
     */
    private BillingClient mBillingClient;

    /**
     * 是否初始化微博
     */
    private boolean isInitWb;

    /**
     * 单列线程池
     */
    private ExecutorService mExecutor;

    /**
     * 当前方式
     */
    private MultiMedia mMultiMedia;

    /**
     * 回调监听
     */
    private OnActionCallback mActionCallback;

    private MultiApi() {
        configs.put(MultiMedia.WECHAT, new PlatformConfig(MultiMedia.WECHAT));
        configs.put(MultiMedia.QQ_PAY, new PlatformConfig(MultiMedia.QQ_PAY));
        configs.put(MultiMedia.UNION_PAY, new PlatformConfig(MultiMedia.UNION_PAY));
        configs.put(MultiMedia.ALIPAY, new PlatformConfig(MultiMedia.ALIPAY));
        configs.put(MultiMedia.QQ, new PlatformConfig(MultiMedia.QQ));
        configs.put(MultiMedia.WEIBO, new PlatformConfig(MultiMedia.WEIBO));
        configs.put(MultiMedia.FACEBOOK, new PlatformConfig(MultiMedia.FACEBOOK));
        configs.put(MultiMedia.GOOGLE, new PlatformConfig(MultiMedia.GOOGLE));
    }

    private static final class Holder {
        private static final MultiApi INSTANCE = new MultiApi();
    }

    public static MultiApi getInstance() {
        return Holder.INSTANCE;
    }

    /**
     * 微信
     *
     * @param appId
     * @param secret
     * @return
     */
    public MultiApi setWechat(String appId, String secret) {
        Platform platForm = getPlatForm(MultiMedia.WECHAT);
        platForm.setAppId(appId);
        platForm.setAppSecret(secret);
        return this;
    }

    /**
     * 云闪付授权登录
     *
     * @param appId
     * @param secret
     * @return
     */
    public MultiApi setUnionPay(String appId, String secret) {
        Platform platForm = getPlatForm(MultiMedia.UNION_PAY);
        platForm.setAppId(appId);
        platForm.setAppSecret(secret);
        return this;
    }

    /**
     * QQ支付
     *
     * @param appId
     * @param secret
     * @return
     */
    public MultiApi setQQPay(String appId, String secret) {
        Platform platForm = getPlatForm(MultiMedia.QQ_PAY);
        platForm.setAppId(appId);
        platForm.setAppSecret(secret);
        return this;
    }

    /**
     * QQ登录和分享
     *
     * @param appId
     * @param secret
     * @return
     */
    public MultiApi setQQ(String appId, String secret) {
        Platform platForm = getPlatForm(MultiMedia.QQ);
        platForm.setAppId(appId);
        platForm.setAppSecret(secret);
        return this;
    }

    /**
     * 支付宝分享
     *
     * @param appId
     * @return
     */
    public MultiApi setAlipay(String appId) {
        Platform platForm = getPlatForm(MultiMedia.ALIPAY);
        platForm.setAppId(appId);
        return this;
    }

    /**
     * 微博授权登录、分享
     *
     * @param appId
     * @param redirectUrl 微博第三方应用授权回调页面。建议使用默认回调页https://api.weibo.com/oauth2/default.html ，可以在新浪微博开放平台->我的应用->应用信息->高级应用->授权设置->应用回调页中找到。
     * @return
     */
    public MultiApi setWeibo(String appId, String redirectUrl) {
        return setWeibo(appId, redirectUrl, null);
    }

    /**
     * 微博授权登录、分享
     *
     * @param appId
     * @param redirectUrl 微博第三方应用授权回调页面。建议使用默认回调页https://api.weibo.com/oauth2/default.html ，可以在新浪微博开放平台->我的应用->应用信息->高级应用->授权设置->应用回调页中找到。
     * @param scope       信息授权域，用“,”隔开
     * @return
     */
    public MultiApi setWeibo(String appId, String redirectUrl, String scope) {
        Platform platForm = getPlatForm(MultiMedia.WEIBO);
        platForm.setAppId(appId);
        platForm.setAppSecret(redirectUrl);
        platForm.setOther(scope);
        return this;
    }

    /**
     * Facebook 授权登录
     *
     * @param appId
     * @param clientToken
     * @return
     */
    public MultiApi setFacebook(String appId, String clientToken) {
        Platform platForm = getPlatForm(MultiMedia.FACEBOOK);
        platForm.setAppId(appId);
        platForm.setAppSecret(clientToken);
        return this;
    }

    /**
     * Google 授权登录
     *
     * @param serverClientId
     * @return
     */
    public MultiApi setGoogle(String serverClientId) {
        Platform platForm = getPlatForm(MultiMedia.GOOGLE);
        platForm.setAppId(serverClientId);
        return this;
    }

    /**
     * 设置微信、QQ、微博分享provider
     *
     * @param authorities provider对应authorities属性值
     * @return
     */
    public MultiApi setFileProvider(String authorities) {
        this.mAuthorities = authorities;
        return this;
    }

    /**
     * 设置调试模式（有日志输出）
     *
     * @param debug
     * @return
     */
    public MultiApi setDebug(boolean debug) {
        this.isDebug = debug;
        return this;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(@NonNull Context context) {
        this.mContext = context.getApplicationContext();
    }

    /**
     * 获取微信、QQ、微博分享provider
     *
     * @return
     */
    String getFileProvider() {
        return this.mAuthorities;
    }

    /**
     * 获取平台信息
     *
     * @param media
     * @return
     */
    Platform getPlatForm(MultiMedia media) {
        return configs.get(media);
    }

    /**
     * 设置方式
     *
     * @param media
     */
    MultiApi setMultiMedia(MultiMedia media) {
        this.mMultiMedia = media;
        return this;
    }

    /**
     * 设置支付监听
     *
     * @param callback
     */
    MultiApi setActionCallback(OnActionCallback callback) {
        this.mActionCallback = callback;
        return this;
    }

    /**
     * 获取上下文
     *
     * @return
     */
    public Context getContext() {
        return mContext;
    }

    /**
     * 是否安装
     *
     * @param media
     * @return
     */
    public boolean isInstalled(MultiMedia media) {
        InstalledState installedState = installedStateCache.get(media);
        if (installedState != null && SystemClock.uptimeMillis() - installedState.time <= 1000L) {
            return installedState.state;
        }
        boolean state = false;
        try {
            if (media == MultiMedia.WECHAT) {
                IWXAPI api = getWXApi();
                if (api != null) {
                    state = api.isWXAppInstalled();
                    return state;
                }
            } else if (media == MultiMedia.QQ) {
                Tencent api = getTencent();
                if (api != null) {
                    state = api.isQQInstalled(mContext);
                    return state;
                }
            } else if (media == MultiMedia.QQ_PAY) {
                IOpenApi api = getOpenApi();
                if (api != null) {
                    state = api.isMobileQQInstalled();
                    return state;
                }
            } else if (media == MultiMedia.ALIPAY) {
                IAPApi api = getAPApi();
                if (api != null) {
                    state = api.isZFBAppInstalled();
                    return state;
                }
            } else if (media == MultiMedia.WEIBO) {
                getWBApi(null);
                if (mWBApi != null) {
                    state = mWBApi.isWBAppInstalled();
                    return state;
                }
            } else if (media == MultiMedia.FACEBOOK) {
                if (mContext != null) {
                    PackageManager manager = mContext.getPackageManager();
                    manager.getPackageInfo("com.facebook.katana", 0);
                    state = true;
                    return state;
                }
            } else if (media == MultiMedia.UNION_PAY) {
                state = UPPayAssistEx.checkWalletInstalled(mContext, "00", null);
                return state;
            } else if (media == MultiMedia.GOOGLE) {
                if (mContext != null) {
                    try {
                        int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(mContext);
                        state = resultCode == ConnectionResult.SUCCESS;
                        return state;
                    } catch (Throwable t) {
                        t.printStackTrace();
                    }
                    PackageManager manager = mContext.getPackageManager();
                    manager.getPackageInfo("com.google.android.gms", 0);
                    state = true;
                    return state;
                }
            }
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            if (installedState == null) {
                installedStateCache.put(media, new InstalledState(state, SystemClock.uptimeMillis()));
            } else {
                installedState.state = state;
                installedState.time = SystemClock.uptimeMillis();
            }
        }
        return state;
    }

    /**
     * 获取微信对象
     */
    public IWXAPI getWXApi() {
        if (mWXApi == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.WECHAT);
                if (platForm != null && platForm.isConfigured()) {
                    String appId = platForm.getAppId();
                    if (!isDebug) {
                        Log.setLogImpl(new WxLog());
                    }
                    mWXApi = WXAPIFactory.createWXAPI(mContext, appId);
                    mWXApi.registerApp(appId);
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mWXApi = null;
            }
        }
        return mWXApi;
    }

    /**
     * 获取 QQ 钱包支付对象
     */
    public IOpenApi getOpenApi() {
        if (mOpenApi == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.QQ_PAY);
                if (platForm != null && platForm.isConfigured()) {
                    mOpenApi = OpenApiFactory.getInstance(mContext, platForm.getAppId());
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mOpenApi = null;
            }
        }
        return mOpenApi;
    }

    /**
     * 获取 QQ 授权登录和分享对象
     */
    public Tencent getTencent() {
        if (mTencent == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.QQ);
                if (platForm != null && platForm.isConfigured()) {
                    mTencent = Tencent.createInstance(platForm.getAppId(), mContext, mAuthorities);
                    // QQ官方sdk授权
                    Tencent.setIsPermissionGranted(true);
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mTencent = null;
            }
        }
        return mTencent;
    }

    /**
     * 获取支付宝分享对象
     */
    public IAPApi getAPApi() {
        if (mAPApi == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.ALIPAY);
                if (platForm != null && platForm.isConfigured()) {
                    mAPApi = APAPIFactory.createZFBApi(mContext, platForm.getAppId(), false);
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mAPApi = null;
            }
        }
        return mAPApi;
    }

    /**
     * 获取微博授权登录和分享对象
     */
    boolean getWBApi(Callback<IWBAPI> callback) {
        if (mContext == null) {
            if (callback != null) {
                callback.onFailure(-8000, "MultiApi未初始化");
            }
            return false;
        }
        if (mWBApi == null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.WEIBO);
                if (platForm != null && platForm.isConfigured()) {
                    mWBApi = WBAPIFactory.createWBAPI(mContext);
                    mWBApi.setLoggerEnable(isDebug);
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mWBApi = null;
            }
        }
        IWBAPI wbApi = mWBApi;
        if (!isInitWb && wbApi != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.WEIBO);
                if (platForm != null && platForm.isConfigured()) {
                    String scope = platForm.getOther();
                    if (scope == null || scope.isEmpty()) {
                        scope = "email,direct_messages_read,direct_messages_write,"
                                + "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
                                + "follow_app_official_microblog,invitation_write";
                    }
                    AuthInfo authInfo = new AuthInfo(mContext, platForm.getAppId(), platForm.getAppSecret(), scope);
                    wbApi.registerApp(mContext, authInfo, new SdkListener() {

                        @Override
                        public void onInitSuccess() {
                            isInitWb = true;
                            if (callback != null) {
                                callback.onSuccess(wbApi);
                            }
                        }

                        @Override
                        public void onInitFailure(Exception e) {
                            if (callback != null) {
                                String errorMsg = e.getMessage();
                                if (TextUtils.isEmpty(errorMsg)) {
                                    errorMsg = getContext().getString(R.string.multi_api_not_initialized_successfully);
                                }
                                callback.onFailure(-8005, errorMsg);
                            }
                        }
                    });
                }
                return true;
            } catch (Throwable t) {
                if (callback != null) {
                    String errorMsg = t.getMessage();
                    if (TextUtils.isEmpty(errorMsg)) {
                        errorMsg = getContext().getString(R.string.multi_api_not_initialized_successfully);
                    }
                    callback.onFailure(-8005, errorMsg);
                }
            }
        } else if (wbApi != null) {
            if (callback != null) {
                callback.onSuccess(wbApi);
            }
            return true;
        } else {
            if (callback != null) {
                callback.onFailure(-8005, getContext().getString(R.string.multi_api_not_initialized_successfully));
            }
        }
        return false;
    }

    /**
     * 获取Facebook授权登录和分享对象
     */
    public CallbackManager getCallbackManager() {
        if (mCallbackManager == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.FACEBOOK);
                if (platForm != null && platForm.isConfigured()) {
                    if (!FacebookSdk.isInitialized()) {
                        FacebookSdk.setApplicationId(platForm.getAppId());
                        FacebookSdk.setClientToken(platForm.getAppSecret());
                        FacebookSdk.setAutoInitEnabled(true);
                        FacebookSdk.sdkInitialize(mContext);
                    }
                    if (FacebookSdk.isInitialized()) {
                        mCallbackManager = CallbackManager.Factory.create();
                    }
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mCallbackManager = null;
            }
        }
        return mCallbackManager;
    }

    /**
     * 获取Google认证管理对象
     */
    public CredentialManager getCredentialManager() {
        if (mCredentialManager == null && mContext != null) {
            try {
                Platform platForm = getPlatForm(MultiMedia.GOOGLE);
                if (platForm != null && platForm.isConfigured()) {
                    mCredentialManager = CredentialManager.create(mContext);
                }
            } catch (Throwable t) {
                t.printStackTrace();
                mCredentialManager = null;
            }
        }
        return mCredentialManager;
    }

    /**
     * 获取Google 支付对象（需要每次连接都是新的）
     */
    public BillingClient getBillingClient() {
        if (mBillingClient != null && !mBillingClient.isReady()) {
            mBillingClient = null;
        }
        if (mBillingClient == null && mContext != null) {
            try {
                mBillingClient = BillingClient.newBuilder(mContext)
                        .setListener(new PurchasesUpdatedListener() {
                            @Override
                            public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
                                OnActionCallback listener = mActionCallback;
                                mActionCallback = null;
                                MultiMedia media = MultiMedia.GOOGLE;
                                int responseCode = billingResult.getResponseCode();
                                if (responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
                                    int size = purchases.size();
                                    JSONArray jsonArray = new JSONArray();
                                    for (int i = 0; i < size; i++) {
                                        Purchase purchase = purchases.get(i);
                                        String purchaseToken = purchase.getPurchaseToken();
                                        jsonArray.put(purchaseToken);
                                    }
                                    i("Google Pay success. data=" + jsonArray);
                                    post(() -> {
                                        if (listener != null) {
                                            Map<String, String> map = new HashMap<>();
                                            map.put("purchaseTokens", jsonArray.toString());
                                            listener.onComplete(media, map);
                                        }
                                    });
                                } else if (responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
                                    // 用户取消支付
                                    i("Google Pay cancel.");
                                    post(() -> {
                                        if (listener != null) {
                                            listener.onCancel(media);
                                        }
                                    });
                                } else {
                                    // 支付失败，报错
                                    e("Google Pay fail. code=" + responseCode);
                                    String message = billingResult.getDebugMessage();
                                    post(() -> {
                                        if (listener != null) {
                                            listener.onFailure(media, responseCode, message);
                                        }
                                    });
                                }
                            }
                        })
                        .build();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return mBillingClient;
    }

    /**
     * Google Play 连接
     *
     * @param callback
     */
    public boolean startConnection(Callback<Object> callback) {
        return startConnection(getBillingClient(), true, callback);
    }

    /**
     * Google Play 连接
     *
     * @param isSync   结果回调是否为主线程， true 是主线程
     * @param callback
     */
    boolean startConnection(BillingClient billingClient, boolean isSync, Callback<Object> callback) {
        if (billingClient == null) return false;
        if (billingClient.isReady()) {
            if (isSync) {
                post(() -> {
                    if (callback != null) {
                        callback.onSuccess(new Object());
                    }
                });
            } else {
                if (callback != null) {
                    callback.onSuccess(new Object());
                }
            }
            return true;
        }
        try {
            billingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingServiceDisconnected() {
                    mBillingClient = null;
                    e("Google billingServiceDisconnected.");
                }

                @Override
                public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
                    int responseCode = billingResult.getResponseCode();
                    if (responseCode == BillingClient.BillingResponseCode.OK) {
                        // The BillingClient is ready. You can query purchases here.
                        e("Google billingServiceConnected.");
                        if (isSync) {
                            post(() -> {
                                if (callback != null) {
                                    callback.onSuccess(new Object());
                                }
                            });
                        } else {
                            if (callback != null) {
                                callback.onSuccess(new Object());
                            }
                        }
                    } else if (responseCode == BillingClient.BillingResponseCode.SERVICE_DISCONNECTED) {
                        int code = -9800;
                        String msg = billingResult.getDebugMessage();
                        e("Google billingServiceConnected fail. code=" + responseCode + ", message=" + msg);
                        if (isSync) {
                            post(() -> {
                                if (callback != null) {
                                    callback.onFailure(code, msg);
                                }
                            });
                        } else {
                            if (callback != null) {
                                callback.onFailure(code, msg);
                            }
                        }
                    } else {
                        String msg = billingResult.getDebugMessage();
                        e("Google billingServiceConnected fail. code=" + responseCode + ", message=" + msg);
                        if (isSync) {
                            post(() -> {
                                if (callback != null) {
                                    callback.onFailure(responseCode, msg);
                                }
                            });
                        } else {
                            if (callback != null) {
                                callback.onFailure(responseCode, msg);
                            }
                        }
                    }
                }
            });
            return true;
        } catch (Exception e) {
            String message = e.getMessage();
            if (message == null) {
                message = "Google Play connect fail.";
            }
            int code = -9800;
            String msg = message;
            e("Google billingServiceConnect exception.", e);
            if (isSync) {
                post(() -> {
                    if (callback != null) {
                        callback.onFailure(code, msg);
                    }
                });
            } else {
                if (callback != null) {
                    callback.onFailure(code, msg);
                }
            }
        }
        return false;
    }

    /**
     * Google Play 断开连接
     */
    public void endConnection() {
        if (mBillingClient != null && mBillingClient.isReady()) {
            mBillingClient.endConnection();
        }
    }

    /**
     * 确认、消费一次性商品交易，一般在购买成功后
     * <p>
     * 警告！ 所有购买都需要确认。 未能确认购买将导致购买退款。 对于一次性产品，请确保使用此方法作为隐式确认，
     * 或者您可以通过{@link BillingClient#acknowledgePurchase(AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)} 明确确认购买。
     * 对于订阅，请使用{@link BillingClient#acknowledgePurchase(AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)）。
     * 有关详细信息，请参阅 https://developer.android.com/google/play/billing/billing_library_overview#acknowledge。
     *
     * @param purchaseToken 支付令牌
     * @return 是否执行成功，true 执行成功，false 执行失败
     */
    public boolean consume(String purchaseToken, Callback<Object> callback) {
        return consume(purchaseToken, true, callback);
    }

    /**
     * 确认、消费一次性商品交易，一般在购买成功后
     * <p>
     * 警告！ 所有购买都需要确认。 未能确认购买将导致购买退款。 对于一次性产品，请确保使用此方法作为隐式确认，
     * 或者您可以通过{@link BillingClient#acknowledgePurchase(AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)} 明确确认购买。
     * 对于订阅，请使用{@link BillingClient#acknowledgePurchase(AcknowledgePurchaseParams, AcknowledgePurchaseResponseListener)）。
     * 有关详细信息，请参阅 https://developer.android.com/google/play/billing/billing_library_overview#acknowledge。
     *
     * @param purchaseToken 支付令牌
     * @param isSync        结果回调是否为主线程， true 是主线程
     * @return 是否执行成功，true 执行成功，false 执行失败
     */
    private boolean consume(String purchaseToken, boolean isSync, Callback<Object> callback) {
        // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
        // Verify the purchase.
        // Ensure entitlement was not already granted for this purchaseToken.
        // Grant entitlement to the user.
        try {
            BillingClient billingClient = getBillingClient();
            return startConnection(billingClient, false, new Callback<Object>() {
                @Override
                public void onSuccess(@NonNull Object data) {
                    ConsumeParams consumeParams = ConsumeParams.newBuilder()
                            .setPurchaseToken(purchaseToken)
                            .build();
                    billingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
                        @Override
                        public void onConsumeResponse(@NonNull BillingResult billingResult, @NonNull String s) {
                            int responseCode = billingResult.getResponseCode();
                            if (responseCode == BillingClient.BillingResponseCode.OK) {
                                if (isSync) {
                                    post(() -> {
                                        if (callback != null) {
                                            callback.onSuccess(new Object());
                                        }
                                    });
                                } else {
                                    if (callback != null) {
                                        callback.onSuccess(new Object());
                                    }
                                }
                            } else {
                                String msg = billingResult.getDebugMessage();
                                if (isSync) {
                                    post(() -> {
                                        if (callback != null) {
                                            callback.onFailure(responseCode, msg);
                                        }
                                    });
                                } else {
                                    if (callback != null) {
                                        callback.onFailure(responseCode, msg);
                                    }
                                }
                            }
                        }
                    });
                }

                @Override
                public void onFailure(int code, @NonNull String msg) {
                    if (isSync) {
                        post(() -> {
                            if (callback != null) {
                                callback.onFailure(code, msg);
                            }
                        });
                    } else {
                        if (callback != null) {
                            callback.onFailure(code, msg);
                        }
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 查询应用程序中购买的当前已拥有的商品的购买详情（仅返回活动订阅和未使用的一次性购买）
     * <p>
     * 注意：出于安全考虑，建议您通过调用以下 API 之一在后端（如果有）进行购买验证：
     * https://developers.google.com/android-publisher/api-ref/purchases/products/get
     * https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get
     *
     * @return 是否执行成功，true 执行成功，false 执行失败
     */
    public boolean queryPurchase(Callback<List<GooglePurchase>> callback) {
        try {
            BillingClient billingClient = getBillingClient();
            return startConnection(billingClient, false, new Callback<Object>() {

                @Override
                public void onSuccess(@NonNull Object data) {
                    BillingResult supportedResult = billingClient.isFeatureSupported(BillingClient.FeatureType.PRODUCT_DETAILS);
                    if (supportedResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                        // 结算库版本5支持
                        QueryPurchasesParams params = QueryPurchasesParams.newBuilder()
                                .setProductType(BillingClient.ProductType.INAPP)
                                .build();
                        billingClient.queryPurchasesAsync(params, new PurchasesResponseListener() {
                            @Override
                            public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                                int responseCode = billingResult.getResponseCode();
                                if (responseCode == BillingClient.BillingResponseCode.OK) {
                                    List<GooglePurchase> purchases = new ArrayList<>();
                                    for (Purchase purchase : list) {
                                        if (purchase.isAcknowledged()) {
                                            continue;
                                        }
                                        String purchaseToken = purchase.getPurchaseToken();
                                        List<String> products = purchase.getProducts();
                                        String productId = null;
                                        if (!products.isEmpty()) {
                                            productId = products.get(0);
                                        }
                                        purchases.add(new GooglePurchase(productId, purchaseToken, purchase.isAutoRenewing()));
                                    }
                                    post(() -> {
                                        if (callback != null) {
                                            callback.onSuccess(purchases);
                                        }
                                    });
                                } else {
                                    String msg = billingResult.getDebugMessage();
                                    post(() -> {
                                        if (callback != null) {
                                            callback.onFailure(responseCode, msg);
                                        }
                                    });
                                }
                            }
                        });
                    } else {
                        // 结算库版本4支持
                        post(() -> {
                            if (callback != null) {
                                callback.onFailure(-8002, mContext.getString(R.string.multi_api_feature_not_supported));
                            }
                        });
                    }
                }

                @Override
                public void onFailure(int code, @NonNull String msg) {
                    post(() -> {
                        if (callback != null) {
                            callback.onFailure(code, msg);
                        }
                    });
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取单列线程池
     */
    Executor getExecutor() {
        if (mExecutor == null) {
            mExecutor = Executors.newSingleThreadExecutor();
        }
        return mExecutor;
    }

    /**
     * 是否授权
     *
     * @param media
     * @return
     */
    public boolean isAuthorize(MultiMedia media) {
        if (media == MultiMedia.QQ) {
            Tencent tencent = getTencent();
            if (tencent != null) {
                return tencent.isSessionValid();
            }
        } else if (media == MultiMedia.FACEBOOK) {
            CallbackManager callbackManager = getCallbackManager();
            if (callbackManager != null) {
                return AccessToken.isCurrentAccessTokenActive();
            }
        }
        return false;
    }

    /**
     * 删除授权
     *
     * @param media
     * @param listener
     */
    public void deleteOauth(MultiMedia media, OnActionListener listener) {
        if (media == MultiMedia.QQ) {
            Tencent tencent = getTencent();
            if (tencent != null) {
                tencent.logout(mContext);
                if (listener != null) {
                    listener.onComplete(media, new HashMap<>());
                }
            } else {
                if (listener != null) {
                    listener.onFailure(media, -9900, getContext().getString(R.string.multi_api_unknown_error));
                }
            }
        } else if (media == MultiMedia.GOOGLE) {
            CredentialManager credentialManager = getCredentialManager();
            if (credentialManager == null) {
                return;
            }
            ClearCredentialStateRequest clearCredentialStateRequest = new ClearCredentialStateRequest();
            credentialManager.clearCredentialStateAsync(clearCredentialStateRequest, new CancellationSignal(), getExecutor(), new CredentialManagerCallback<Void, ClearCredentialException>() {
                @Override
                public void onResult(Void unused) {
                    if (listener != null) {
                        listener.onComplete(media, new HashMap<>());
                    }
                }

                @Override
                public void onError(@NonNull ClearCredentialException e) {
                    if (listener != null) {
                        listener.onFailure(media, -9900, e.getMessage());
                    }
                }
            });
        } else if (media == MultiMedia.FACEBOOK) {
            CallbackManager callbackManager = getCallbackManager();
            if (callbackManager != null) {
                LoginManager.getInstance().logOut();
                if (listener != null) {
                    listener.onComplete(media, new HashMap<>());
                }
            } else {
                if (listener != null) {
                    listener.onFailure(media, -9900, getContext().getString(R.string.multi_api_unknown_error));
                }
            }
        }
    }

    /**
     * 延迟切换为主线程
     *
     * @param runnable
     */
    public void postDelayed(long delayMillis, Runnable runnable) {
        mHandler.postDelayed(runnable, delayMillis);
    }

    /**
     * 切换为主线程
     *
     * @param runnable
     */
    public void post(Runnable runnable) {
        mHandler.post(runnable);
    }

    /**
     * 结果处理
     *
     * @param media
     * @param intent
     */
    public void handleIntent(MultiMedia media, Intent intent) {
        OnActionCallback callback = mActionCallback;
        release();
        i("handleIntent MultiMedia=" + media);
        if (MultiMedia.WECHAT == media) {
            try {
                IWXAPI api = getWXApi();
                if (api != null) {
                    api.handleIntent(intent, new WXEventHandler(callback));
                }
            } catch (Throwable t) {
                if (callback != null) {
                    callback.onFailure(media, -9004, t.getMessage());
                }
            }
        } else if (MultiMedia.QQ_PAY == media) {
            try {
                IOpenApi api = getOpenApi();
                if (api != null) {
                    api.handleIntent(intent, new QQPayHandler(callback));
                }
            } catch (Throwable t) {
                if (callback != null) {
                    callback.onFailure(media, -9004, t.getMessage());
                }
            }
        } else if (MultiMedia.ALIPAY == media) {
            try {
                IAPApi api = getAPApi();
                if (api != null) {
                    api.handleIntent(intent, new AlipayEventHandler(callback));
                }
            } catch (Throwable t) {
                if (callback != null) {
                    callback.onFailure(media, -9004, t.getMessage());
                }
            }
        }
    }

    /**
     * activity 结果处理
     *
     * @param activity
     * @param requestCode
     * @param resultCode
     * @param data
     */
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
        MultiMedia media = mMultiMedia;
        OnActionCallback callback = mActionCallback;
        release();
        Context context = getContext();
        if (context == null) {
            return;
        }
        i("onActivityResult MultiMedia=" + media + ", requestCode=" + requestCode + ", resultCode=" + resultCode);
        if (MultiMedia.UNION_PAY == media) {
            // 云闪付
            if (requestCode == 1 || requestCode == 2) {
                // 授权登录
                /**
                 * "status_code" String 状态码（必有）， “00”:认证成功，“01”:用户取消，“02”:认证失败
                 * "authcode" String 用于后续操作（仅成功时会有）
                 * "state" String 用于保持请求和回调的状态，授权请求后原样带回给第三方。该参数可用于防止csrf攻击（仅成功时会有）
                 * "errormsg" String 用于定位失败原因(仅失败时会有)
                 * "errorcode" String 用于定位失败原因(仅失败时会有)
                 * “extradata” String 用于定位失败原因(仅失败时会有)，错误码为“98”时返回，值为最新版“云闪付”下载url
                 */
                HashMap<String, String> resultMap = UPAuthStart.UPAuthActivityResult(data);
                if (resultMap != null) {
                    String status = resultMap.get("status_code");
                    i("onActivityResult UNION_PAY status_code=" + status);
                    if ("00".equals(status)) {
                        // 成功
                        /*String state = resultMap.get("state");
                        if (state == null) {
                            return;
                        }*/
                        Map<String, String> map = new HashMap<>();
                        map.put("authCode", resultMap.get("authcode"));
                        if (callback != null) {
                            callback.onComplete(MultiMedia.UNION_PAY, map);
                        }
                    } else if ("01".equals(status)) {
                        // 取消
                        if (callback != null) {
                            callback.onCancel(MultiMedia.UNION_PAY);
                        }
                    } else if ("02".equals(status)) {
                        // 失败
                        int errorCode = -9900;
                        String errorMsg = "";
                        try {
                            String errorCodeStr = resultMap.get("errorcode");
                            errorMsg = resultMap.get("errormsg");
                            if (!TextUtils.isEmpty(errorCodeStr)) {
                                errorCode = Integer.parseInt(errorCodeStr);
                            }
                        } catch (Throwable t) {
                            t.printStackTrace();
                        }
                        if (TextUtils.isEmpty(errorMsg)) {
                            errorMsg = context.getString(R.string.multi_api_unknown_error);
                        }
                        if (callback != null) {
                            callback.onFailure(MultiMedia.UNION_PAY, errorCode, errorMsg);
                        }
                    } else {
                        // 未知错误
                        if (callback != null) {
                            callback.onFailure(MultiMedia.UNION_PAY, -9900, context.getString(R.string.multi_api_unknown_error));
                        }
                    }
                } else {
                    if (callback != null) {
                        callback.onFailure(MultiMedia.UNION_PAY, -9006, context.getString(R.string.multi_api_result_data_empty));
                    }
                }
            } else if (requestCode == 10) {
                // 支付回调处理
                if (resultCode != Activity.RESULT_OK) {
                    if (callback != null) {
                        callback.onFailure(media, -9005, context.getString(R.string.multi_api_result_status_error));
                    }
                } else if (data != null) {
                    /*
                     * 支付控件返回字符串:success、fail、cancel 分别代表支付成功，支付失败，支付取消
                     */
                    String str = data.getStringExtra("pay_result");
                    if ("success".equalsIgnoreCase(str)) {
                        if (callback != null) {
                            Map<String, String> map = new HashMap<>();
                            String resultData = data.getStringExtra("result_data");
                            i("onActivityResult UNION_PAY pay success. resultData=" + resultData);
                            try {
                                JSONObject resultJson = new JSONObject(resultData);
                                map.put("sign", resultJson.getString("sign"));
                                map.put("data", resultJson.getString("data"));
                            } catch (Throwable t) {
                                t.printStackTrace();
                            }
                            callback.onComplete(media, map);
                        }
                    } else if ("fail".equalsIgnoreCase(str)) {
                        if (callback != null) {
                            callback.onFailure(media, -9900, context.getString(R.string.multi_api_unknown_error));
                        }
                    } else if ("cancel".equalsIgnoreCase(str)) {
                        if (callback != null) {
                            callback.onCancel(media);
                        }
                    }
                } else {
                    if (callback != null) {
                        callback.onFailure(media, -9006, context.getString(R.string.multi_api_result_data_empty));
                    }
                }
            }
        } else if (MultiMedia.QQ == media) {
            if (callback != null) {
                Tencent tencent = getTencent();
                if (tencent != null) {
                    i("onActivityResult QQ resultData handler.");
                    Tencent.onActivityResultData(resultCode, resultCode, data, new QQEventHandler(tencent, callback));
                }
            }
        } else if (MultiMedia.WEIBO == media) {
            getWBApi(new Callback<IWBAPI>() {
                @Override
                public void onSuccess(@NonNull IWBAPI api) {
                    if (api.isAuthorizeResult(requestCode, resultCode, data)) {
                        i("onActivityResult WEIBO AuthorizeResult handler.");
                        api.authorizeCallback(activity, requestCode, resultCode, data);
                    } else if (api.isShareResult(requestCode, resultCode, data)) {
                        i("onActivityResult WEIBO ShareResult handler.");
                        api.doResultIntent(data, new WbShareCallback(callback));
                    }
                }

                @Override
                public void onFailure(int code, @NonNull String msg) {

                }
            });
        } else if (MultiMedia.FACEBOOK == media) {
            // Facebook
            CallbackManager callbackManager = getCallbackManager();
            if (callbackManager != null) {
                i("onActivityResult FACEBOOK ShareResult handler.");
                callbackManager.onActivityResult(resultCode, resultCode, data);
            }
        }
    }

    /**
     * onResume 方法中调用
     * 该方法仅微信授权登录、支付、分享，QQ支付，支付宝分享生效
     *
     * @return 是否回调成功
     */
    public boolean resume() {
        MultiMedia media = mMultiMedia;
        OnActionCallback callback = mActionCallback;
        release();
        Context context = getContext();
        if (context == null) {
            return false;
        }
        if (callback == null) {
            return false;
        }
        i("resume MultiMedia=" + media);
        if (MultiMedia.WECHAT == media) {
            int action = callback.getAction();
            if (action == 3) {
                callback.onComplete(media, new HashMap<>());
            } else {
                callback.onFailure(media, -8008, context.getString(R.string.multi_api_no_response_data_available));
            }
            return true;
        } else if (MultiMedia.QQ_PAY == media) {
            callback.onFailure(media, -8008, context.getString(R.string.multi_api_no_response_data_available));
            return true;
        } else if (MultiMedia.ALIPAY == media) {
            int action = callback.getAction();
            if (action == 3) {
                callback.onComplete(media, new HashMap<>());
                return true;
            }
        }
        return false;
    }

    /**
     * 异步post
     *
     * @param r
     */
    boolean postAsync(@NonNull Runnable r) {
        Executor executor = getExecutor();
        executor.execute(r);
        return true;
    }

    /**
     * 发起请求
     *
     * @param url      请求地址
     * @param callback 回调
     */
    boolean request(@NonNull String url, Callback<JSONObject> callback) {
        Executor executor = getExecutor();
        executor.execute(() -> {
            InputStream in = null;
            try {
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                HttpsURLConnection httpsConn = (HttpsURLConnection) urlConnection;
                httpsConn.setAllowUserInteraction(false);
                httpsConn.setInstanceFollowRedirects(true);
                httpsConn.setRequestMethod("GET");
                httpsConn.connect();
                int resCode = httpsConn.getResponseCode();
                String resMsg = httpsConn.getResponseMessage();
                if (resCode == HttpURLConnection.HTTP_OK) {
                    in = httpsConn.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"), 8);
                    StringBuilder sb = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                    }
                    in.close();
                    String httpResult = sb.toString();
                    final JSONObject jsonObject = new JSONObject(httpResult);
                    if (callback != null) {
                        callback.onSuccess(jsonObject);
                    }
                } else {
                    if (resMsg == null) {
                        resMsg = "";
                    }
                    if (callback != null) {
                        callback.onFailure(resCode, resMsg);
                    }
                }
                httpsConn.disconnect();
            } catch (Exception e) {
                if (callback != null) {
                    String msg = e.getMessage();
                    if (msg == null) {
                        msg = "";
                    }
                    callback.onFailure(-9900, msg);
                }
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        return true;
    }

    /**
     * 释放对象
     */
    public void release() {
        mMultiMedia = null;
        mActionCallback = null;
    }

    /**
     * 销毁所有对象（除Context）
     */
    public void destroy() {
        release();
        i("MultiApi object destroy.");
        installedStateCache.clear();
        if (mWXApi != null) {
            try {
                mWXApi.unregisterApp();
            } catch (Exception e) {
            }
            mWXApi.detach();
        }
        mWXApi = null;
        mOpenApi = null;
        mTencent = null;
        mAPApi = null;
        mWBApi = null;
        isInitWb = false;
        mCallbackManager = null;
        mCredentialManager = null;
        if (mExecutor != null) {
            mExecutor.shutdown(); // 禁用新任务
            try {
                // 等待现有任务完成
                if (!mExecutor.awaitTermination(60, TimeUnit.SECONDS)) {
                    mExecutor.shutdownNow(); // 取消正在执行的任务
                }
            } catch (Exception ie) {
                try {
                    mExecutor.shutdownNow();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        mExecutor = null;
    }

    void i(String msg) {
        if (!isDebug) {
            return;
        }
        android.util.Log.i("MultiApiSdk", msg);
    }

    void e(String msg) {
        if (!isDebug) {
            return;
        }
        android.util.Log.e("MultiApiSdk", msg);
    }

    void e(String msg, Throwable t) {
        if (!isDebug) {
            return;
        }
        android.util.Log.e("MultiApiSdk", msg, t);
    }
}
